from individual import Individual
import numpy as np
class Population:
    def __init__(self, num_pops, m_num_matrix=1, m_num_op_list=1):
        self.num_pops = num_pops
        self.pops = []
        for i in range(num_pops):
            indi = Individual(m_num_matrix, m_num_op_list)
            # print(dir(indi), indi.win_time)
            indi.initialize()
            self.pops.append(indi)                                         # time和accuracy都没有赋值   pops [indi,indi,indi]

    def copy_acc_time_from_Population(self, copy_population):
        assert len(self.pops) == len(copy_population.pops)
        for i, indi in enumerate(copy_population.pops):
            self.pops[i].mean_acc = indi.mean_acc
            self.pops[i].win_time = indi.win_time
            self.pops[i].mean_training_time = indi.mean_training_time      # pops[i]表示第i个indi，这里是将另一个pop的time和accuracy赋值给当前pops？

    def calculate_population_training_time(self):
        total_training_time = 0
        for i in range(self.get_pop_size()):
            indi_i = self.get_individual_at(i)
            total_training_time += indi_i.mean_training_time

        return total_training_time                                          # 计算总时间

    def get_individual_at(self, i):
        return self.pops[i]

    def get_pop_size(self):
        return len(self.pops)                                               # 得到pops的个体数目,即indi数目

    def set_populations(self, new_pops):
        self.pops = new_pops                                                # 旧pops换成新pops

    # append new pops to the current self.pops
    def merge_populations(self, new_pops):
        for indi in new_pops:
            self.pops.append(indi)                                          # 新pops合并到旧pops后面

    def add_individual(self, new_indi: Individual):
        self.pops.append(new_indi)                                          # 加入一个新个体到pops后面

    def get_best_acc(self):
        mean_acc_list = []
        for i in range(self.get_pop_size()):
            indi = self.get_individual_at(i)
            mean_acc_list.append(indi.mean_acc)
        return np.max(mean_acc_list)                                        # 获得pops中的最高精度

    def get_sorted_index_order_by_win(self):
        win_list = []
        for i in range(self.get_pop_size()):
            indi = self.get_individual_at(i)
            win_list.append(indi.win_time)
        arg_index = np.argsort(-1 * np.array(win_list))
        return arg_index                                                   # get_sorted_index_order_by_win
    def get_sorted_index_order_by_acc(self):
        mean_acc_list = []
        for i in range(self.get_pop_size()):
            indi = self.get_individual_at(i)
            mean_acc_list.append(indi.mean_acc)
        arg_index = np.argsort(-1 * np.array(mean_acc_list))
        return arg_index                                                   # get_sorted_index_order_by_acc
    def __str__(self):
        _str = []
        arg_index = self.get_sorted_index_order_by_win()                   # 精度排序
        for i in arg_index:
            _str.append(str(self.get_individual_at(i)))                    #   按要求打印indi
        return '\n'.join(_str)


if __name__ == '__main__':
    pop = Population(num_pops=20, m_num_matrix=2, m_num_op_list=2)
    b= Population(num_pops=0, m_num_matrix=2, m_num_op_list=2)
    c = Population(num_pops=0, m_num_matrix=2, m_num_op_list=2)
    pop.pops[3].win(1)
    a=pop.get_sorted_index_order_by_win()
    for i in a[:]:
        b.add_individual(pop.get_individual_at(i))
    print(a)
    for indix0, indi0 in enumerate(b.pops):
        matrix0 = indi0.indi['matrix']
        print(matrix0)

